#ifndef SDCARD_HPP
#define SDCARD_HPP

#include <stdint.h>

#define FLAG(x) (0x01 << x)
#define FLAG_SET(r,x) (r |= x)
#define FLAG_CLEAR(r,x) (r &= ~x)

class SDCardCallback {
public:
    virtual uint8_t busInit(void) = 0;
    virtual uint8_t setSpeed(uint8_t speed) = 0;
    virtual uint8_t readWriteByte(uint8_t byte) = 0;
    virtual uint8_t setEnable(uint8_t status) = 0;
};

class SDCard{
public:
    /* 总线类型 */
    enum class BusType {
        Bus_SDIO,
        Bus_SPI
    };
    /* 卡类型 */
    enum class CardType {
        Unknown,
        MMC,
        V1,
        V2,
        V2HC
    };
    /* 卡信息 */
    class CardInfo{
    public:
        CardType type;      /* 卡类型 */
        uint32_t blockSize; /* 单位读写的块大小 */
        uint32_t capacity;  /* 卡容量（块单位） */
    };
public:
    static const uint32_t Flag_Initialized = FLAG(0);
public:
    SDCard(SDCardCallback *callback,BusType bus);
    uint8_t writeBlock(uint8_t *buff,uint32_t startBlock,uint32_t count);
    uint8_t readBlock(uint8_t *buff,uint32_t startBlock,uint32_t count);
    CardInfo getInfo(void);

private:
    uint8_t sendCommand(uint8_t cmd,uint32_t arg,uint8_t crc);

private:
    BusType busType;            /* 总线类型 */
    CardInfo info;          /* 卡信息 */
    SDCardCallback *callback;   /* 回调函数集 */
    uint32_t flag;              /* 卡标志 */
    char csd[16];               /* CSD寄存器 */
};

#endif